package client

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/liushuochen/gotable"
)

//本地存储json
type LmctlJson struct{
    Ownership string `json:"ownership"`
    Authorization string `json:"authorization"`
    Url string `json:"url"`
}
//返回数据 struct
type License struct {
    Id int `json:"id,omitempty"`//指定 id
	Custom string `json:"custom,omitempty"` //客户
    Product string `json:"product,omitempty"` //产品
    ExpirDate string `json:"expirDate,omitempty"` //过期时间(支持续签)
    Status string `json:"status,omitempty"` //当前状态(有效/无效)
    PubKey string `json:"pubkey,omitempty"` //公钥
    PrivateKey string `json:"privatekey,omitempty"` //私钥
    IdentificationCode string `json:"identificationcode,omitempty"` //企业识别码
    Ownership string `json:"ownership,omitempty"` //维护人员
    Ipaddress string `json:"ipaddress,omitempty"` //注册IP地址
    Remark string `json:"remark,omitempty"` //备注
    CreateTime string `json:"createTime,omitempty"` //创建时间
    UpdateTime string `json:"updateTime,omitempty"` //更新时间
}

//Method 指定方法 url 请求url地址 Authorization 指定token jsonData 发送data数据
func HttpCtx(Method string,url string,Authorization string,jsonData []byte)(map[string]interface{}){
    var err error
    var req *http.Request
    if len(jsonData) == 0{
        req,err = http.NewRequest(Method, url, nil)
    }else{
        req,err = http.NewRequest(Method, url, bytes.NewBuffer(jsonData))
    }
    
	if err != nil {
        log.Println("创建请求失败:", err)
		panic(err.Error())
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", Authorization)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println("发送请求失败:", err)
		panic(err.Error())
	}
	defer resp.Body.Close()
    contentType := resp.Header.Get("Content-Type")
    if strings.HasPrefix(contentType, "application/json"){
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            log.Println("读取响应失败:", err)
            panic(err.Error()) 
        }
        var response map[string]interface{}
        err = json.Unmarshal(body, &response)
        if err != nil{
            log.Println(err.Error())
            panic(err.Error())
        }
        return response
    }else if strings.HasPrefix(contentType, "application/octet-stream"){
		err = downloadFile("cipher.pem", resp.Body)
		if err != nil {
			log.Println("Error downloading file:", err)
		} else {
			log.Println("文件下载完成")
		}
    }else{
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            log.Println("读取响应失败:", err)
            panic(err.Error()) 
        }
        var response map[string]interface{}
        err = json.Unmarshal(body, &response)
        if err != nil{
            log.Println(err.Error())
            panic(err.Error())
        }
        return response
    }
    var response map[string]interface{}
    return response
}

func downloadFile(filepath string, body io.ReadCloser) error {
	defer body.Close()

	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, body)
	return err
}

//删除
func LmDelete(id int)(){
    prefix := "/delete/license"
    LmJson := QueryUserConfig()
    Authorization := LmJson.Authorization
    Url := LmJson.Url
    person := struct {
        Id int `json:"id"`
    }{Id: id}
    jsonData, err := json.Marshal(person)
    if err != nil{
        log.Println(err.Error())
        return
    }
    
    // log.Println(string(jsonData),fmt.Sprintf("%s%s",Url,prefix),Authorization)
    response := HttpCtx("DELETE",fmt.Sprintf("%s%s",Url,prefix),Authorization,jsonData)
    code := response["code"].(float64)
    if code == 200{
        return
    }else{
        log.Println("删除异常",response["message"].(string))
    }
}

//添加更新
func LmApply(file string )(){
    LmJson := QueryUserConfig()
    Authorization := LmJson.Authorization
    Url := LmJson.Url
    Ownership := LmJson.Ownership //维护人员
	jsonData, err := ioutil.ReadFile(file)
	if err != nil {
		log.Println("无法读取文件:", err)
		return
	}
	var license License
	err = json.Unmarshal(jsonData, &license)
	if err != nil {
		log.Println("无法解析 JSON 数据:", err)
		return
	}
    license.Ownership = Ownership
    jsonData,err = json.Marshal(license)
    if err != nil {
        log.Println("无法解析 JSON 数据:", err)
        return
    }
    if license.Id == 0{
        prefix := "/add/license"
        // log.Println(string(jsonData),fmt.Sprintf("%s%s",Url,prefix),Authorization)
        response := HttpCtx("POST",fmt.Sprintf("%s%s",Url,prefix),Authorization,jsonData)
        code := response["code"].(float64)
        if code == 200 {
            return
        }else{
            log.Println("添加失败",response["message"].(string))
            return
       }
    }else{
        prefix := "/update/license"
        // log.Println(string(jsonData),fmt.Sprintf("%s%s",Url,prefix),Authorization)
        response := HttpCtx("POST",fmt.Sprintf("%s%s",Url,prefix),Authorization,jsonData)
        code := response["code"].(float64)
        if code == 200 {
            return
        }else{
            log.Println("更新失败",response["message"].(string))
            return
    }
    }
}

//处理struct to []map[string]string
func StructToMap(license []License)([][]string){
    var maps [][]string
	for _, p := range license {
        strSlice := []string{strconv.Itoa(p.Id),p.Custom,p.Product,p.ExpirDate,p.Status,p.Ownership,p.Ipaddress,p.Remark,p.CreateTime,p.UpdateTime}
        maps = append(maps, strSlice)
	}
    return maps
}

//查询
func LmGet(id int)(){
    if id == 0{
        prefix := "/get/license/all"
        LmJson := QueryUserConfig()
        Authorization := LmJson.Authorization
        Url := LmJson.Url
        // log.Println(fmt.Sprintf("%s%s",Url,prefix),Authorization)
        response := HttpCtx("GET",fmt.Sprintf("%s%s",Url,prefix),Authorization,make([]byte, 0))
        code := response["code"].(float64)
        if code == 200 {
            data := response["data"].(string)
            var license []License
            err := json.Unmarshal([]byte(data),&license)
            if err != nil{
                log.Println(err.Error(),"query json Unmarshal failed")
                return
            }
            table, err := gotable.Create("id", "客户","产品","过期时间","当前状态","维护人员","地址","备注","创建时间","更新时间")
            values := StructToMap(license)
            for _,rows := range values{
                table.AddRow(rows)
            }
            log.Println(table)
        }else{
            log.Println("query failed",response["message"].(string))
            return
        }
    }else{
        prefix := "/get/license/all"
        LmJson := QueryUserConfig()
        Authorization := LmJson.Authorization
        Url := LmJson.Url
        log.Println(fmt.Sprintf("%s%s",Url,prefix),Authorization)
        response := HttpCtx("GET",fmt.Sprintf("%s%s",Url,prefix),Authorization,make([]byte, 0))
        code := response["code"].(float64)
        if code == 200{
            data := response["data"].(string)
            var license []License
            err := json.Unmarshal([]byte(data),&license)
            if err != nil{
                log.Println(err.Error(),"query json Unmarshal failed")
                return
            }
            table, err := gotable.Create("id", "客户","产品","过期时间","当前状态","维护人员","地址")
            values := StructToMap(license)
            for _,rows := range values{
                table.AddRow(rows)
            }
            log.Println(table)
        }else{
            return
        }
    }
}




//登录

func ApiLogin(Url string,Authorization string)(){
    prefix := "/get/user/info"
    response := HttpCtx("GET",fmt.Sprintf("%s%s",Url,prefix),Authorization,make([]byte, 0))
    code := response["code"].(float64)
    if code == 200{
        ResponseData := response["data"].(string)
        var data []map[string]interface{}
        err := json.Unmarshal([]byte(ResponseData), &data)
        if err != nil {
            log.Println("Error:", err)
            return
        }
        ownership := data[0]["user"].(string)
        var LmJson LmctlJson
        LmJson.Ownership = ownership
        LmJson.Authorization = Authorization
        LmJson.Url= Url
        jsonData, err := json.Marshal(LmJson)
        if err != nil {
		    log.Println("无法序列化 JSON 数据:", err)
		    panic(err.Error())
	    }
	    usr, err := user.Current()
	    if err != nil {
		    log.Println("无法获取当前用户信息:", err)
		    return
	    }
        filePath := filepath.Join(usr.HomeDir, "lmctl.json")
        err = ioutil.WriteFile(filePath, jsonData, 0644)
        if err != nil {
            log.Println("无法写入文件:", err)
            return
        }
        log.Println("login succeeded")
    }else{
        log.Println("login failed")
    }
}

//查询当前用户对应token/url/ownership
func QueryUserConfig()(LmctlJson){
    usr, err := user.Current()
	if err != nil {
		log.Println("无法获取当前用户信息:", err)
        panic(err.Error())
	}
    filePath := filepath.Join(usr.HomeDir, "lmctl.json")
	jsonData, err := ioutil.ReadFile(filePath)
	if err != nil {
		log.Println("无法读取文件:", err)
        panic(err.Error())
	}
	var LmJson LmctlJson
	err = json.Unmarshal(jsonData, &LmJson)
	if err != nil {
		log.Println("无法解析 JSON 数据:", err)
        panic(err.Error())
	}
    return LmJson
}

//下载有效期加密符
func DownloadRsa(id int){
    prefix :=  fmt.Sprintf("/get/rsa?id=%d&genname=ciphertext",id)
    LmJson := QueryUserConfig()
    Authorization := LmJson.Authorization
    Url := LmJson.Url
    response := HttpCtx("GET",fmt.Sprintf("%s%s",Url,prefix),Authorization,make([]byte, 0))
    // code := response["code"].(float64)
    log.Println(response)

}